Repository navigation
feat(cli): os mcp connect registers your environment's MCP server with Claude Code - #31149
Conversation
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ihL2dLQEXWGsE2SZ3Qn5F
… Claude Code Resolves the environment the way os deploy does, reads its hostname from the control plane, and runs (or with --print, prints) claude mcp add with the URL alone, named after the environment. --url covers a self-hosted or local server. No token is stored or handed to the client. os dev's Connect row now prints through the same line builder. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ihL2dLQEXWGsE2SZ3Qn5F
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ihL2dLQEXWGsE2SZ3Qn5F
📓 Docs Drift CheckThis PR changes 1 package(s): 39 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 7 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 35 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 3df1d140b5216d8c4772dc8d151f45bba201490c && git checkout 3df1d140b5216d8c4772dc8d151f45bba201490c
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 9f61e06e6fe4d28c0fcc6ef66b3fcfef6067e51b df587407a11631e548aa03e9b6873f3f226f7e72 && git checkout -B drift-repro 9f61e06e6fe4d28c0fcc6ef66b3fcfef6067e51b && git merge --no-ff df587407a11631e548aa03e9b6873f3f226f7e72
node scripts/docs-audit/affected-docs.mjs --json 9f61e06e6fe4d28c0fcc6ef66b3fcfef6067e51b
|
|
domain:server#4 · marchtian · session_017ihL2dLQEXWGsE2SZ3Qn5F 席位核对 — ACCEPT · domain:server#4 · Head-sha:
|
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 42385456389 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 分类: 失败的 job(日志抽取,best effort):
跨 PR 相同签名(24h,按失败测试文件聚合):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
|
domain:server#4 · marchtian · session_017ihL2dLQEXWGsE2SZ3Qn5F Queue ejection read · build 42385456389 ·
|
Requested by 田騏 · project thread
Fixes #30889
Clause-②: no
Metadata-protocol: none
维护者速读
os mcp connect:自动找到os deploy用的那个云端环境(--env→ 当前激活环境 → 组织唯一环境),读出它的地址,执行claude mcp add --transport http 环境名 https://环境域名/api/v1/mcp;--print只打印不执行,--url连自托管或本地服务。os dev横幅的 Connect 行改为用同一个拼写函数。os dev有提示,云端没有。现在一条命令完成,登录授权交给 Claude Code 按环境自己的 OAuth 在浏览器里做。--env时同样拒绝。回滚即 revert 本 PR,os dev横幅输出字节不变。packages/cli/src/commands/mcp/connect.ts(命名与--url规则、执行claude的分支);packages/cli/src/utils/served-version.ts(环境详情读取改成可报错的readCloudEnvironment,deploy 的fetchEnvironmentOrigin包在它外面);packages/cli/test/mcp-connect.test.ts。pnpm --filter @objectstack/cli exec vitest run test/mcp-connect.test.ts,预期 14 个用例全过;或本地os dev起服务后跑os mcp connect --url http://localhost:3000 --print,打印的 Connect 行与os dev横幅那行一字不差。What changes
os mcp connect(packages/cli/src/commands/mcp/connect.ts).resolveInstallTarget, the functionos deployandos package publish --installuse (--env/$OS_ENVIRONMENT_ID, then the active environment for this control plane, then the organization's only environment). None or several ⇒ the same refusal naming--env, exit 1. The only edit to it is an optionalpurposeso the refusal reads "needs an environment to connect to"; the default wording is unchanged.hostnamefromGET /api/v1/cloud/environments/ID, plus/api/v1/mcp. The read isreadCloudEnvironmentinutils/served-version.ts; deploy'sfetchEnvironmentOriginnow wraps it, so the hostname-to-origin rule stays in one place. An unreadable environment or one with no hostname is refused before anything runs.-. So several environments can be registered side by side.--nameoverrides it and must be letters, digits,-and_.--url BASEskips the control plane (self-hosted or localos dev). The name defaults toobjectstack, the nameos dev's banner and the servedSKILL.mdalready use. A URL that already ends in/api/v1/mcp, carries a query, or is not http(s) is refused rather than guessed.--printit runsclaude mcp add --transport http NAME URL(argv, no shell except on Windows for the.cmdshim).claudemissing ⇒ exit 1 with the line to paste.claudefailing ⇒ its exit code.--printprints the endpoint and the line and runs nothing.--clientaccepts onlyclaude-codetoday./mcpin Claude Code (the browser shows the environment's sign-in and consent; no token was stored); revoke in the environment's console under Account → Connect an AI Assistant; and the epic's model line (MCP reads the environment for context; a managed package's content changes through its source andos deploy, not through MCP).os dev's Connect row now prints through the sameclaudeMcpAddLinebuilder andMCP_ENDPOINT_PATH. Its output is byte-identical. The existing source pin indev-mcp-connect-hint-origin.test.tsnow asserts the builder call instead of the inline literal.@objectstack/clipatch.Tests
packages/cli/test/mcp-connect.test.ts, 14 cases. It uses the same harness shape astest/deploy.test.ts: the real command, realcloud.jsonunder a redirected$HOME,fetchas the control plane, and the client runner standing in forclaude.--print⇒ that environment's MCP URL andclaude mcp addline, named for the environment, nothing run.--url http://localhost:3000⇒ the local line, no control-plane call. The test also asserts thatprintMcpConnectHint({ boundPort: 3000 })prints the identical line.--env⇒ exit 1 with deploy's refusal, nothing registered.claudeexactlymcp add --transport http acme https://acme.example.test/api/v1/mcp. No argument carries the cloud token or a header, the output never prints the token, and every file under$HOMEand the working directory is byte-identical before and after.--envwith the name from the detail read, no hostname / 404 refusals, not logged in,claudenot on PATH,claudeexit-code passthrough,--nameoverride and refusal, and the name / base-URL helpers.Acceptance notes
--printcovers them: add the printed endpoint as a remote HTTP MCP server in the client's settings. Adding one later means a new--clientvalue with a cited config shape.os cloud loginagainst staging, thenos mcp connect, then/mcpin Claude Code and one browser consent; Claude Code should list the environment's tools. Then revoke the assistant under Account → Connect an AI Assistant; the next tool call should fail.content/docs/deployment/cli.mdxis not touched because it is outside the claim's file surface. The command's--helpcarries the description, the examples and every flag.AuthorizedAccessListlists and revokes the person's authorized assistants. No stable console URL for that page could be confirmed.Verification
Local runs on head df58740 (all exit codes captured before any pipe):
Derived gate families: 63 of 63 exit 0 on df58740 (dispatch-gates --ran: 63 run, 0 NOT-MEASURED, a derived zero)
Package runs on df58740
The integration tier is left to CI: the diff touches no integration-tier file and no spawn entry.
🤖 Generated with Claude Code